
// Mason D. Hill, Assignment #5
// Youtube link: https://www.youtube.com/watch?v=VRY61K-eA6M
#define F_CPU 8000000UL // 8 mhz

#include <util/delay.h> // delay library
#include <avr/io.h> // input/output library
#include <avr/interrupt.h>//interrupt library


int outputadded = 0; // Holds the analog read value

int numbersinverse[4]; // holds the value to be sent to terminal/LED
int softtime = 0; // Used to make it clock to 1 second

void outputnumber2terminal(int n);
void digit_send(int number);
void usart_send(unsigned char ch);


ISR(TIMER1_OVF_vect){
	
	
	/// This happens every 1/2 second. To obtain every second, need to software timer it by 1 more.


	if(softtime==2){ // Check for every other go, so to bring 1/2 second to 1 second
		softtime=0; // Set softtime back to 0
		
		numbersinverse[0] = 0; // Clear the first value of the numbersinverse
		numbersinverse[1] = 0; // Clear the second value of the numbersinverse
		numbersinverse[2] = 0; // Clear the third value of the numbersinverse
		numbersinverse[3] = 0; // Clear the fourth value of the numbersinverse
		
		
		int inf = (outputadded*10) * 9 /5 +3200; // This converts from celsius to farenheit. The chip we had measured in C. +3200 is due to the value being in int. It is scaled by 2. 3200 really is 32.00
		outputnumber2terminal(inf); // Send the value to terminal
		

		int inft = inf; // Make a copy of in farenheit so to be able to inverse the number
		int i2 = 3; // Read from right to left
		
		
		do {
			
			int digit = inft % 10; // Get the smallest digit
			numbersinverse[i2] = digit; // Set the smallest digit to the right of number to inverse
			inft /= 10; // Divide it by 10, so to move to the next digit
			i2--; // Go to next digit

		} while (inft > 0); // Continue until all numbers are read
		
		
		
	}
	
	
	softtime++; // Increment
}







void usart_init (void)
{
	UCSR0B = (1<<RXEN0)|(1<<TXEN0); // Enable transmit and recieve
	UCSR0C = ((1<<UCSZ01)|(1<<UCSZ00)|(0<<UMSEL00)); // Sends it to be unsyncronise.
	UBRR0L = 51; // Sets the scalar value (9600 baud)
	
}
void adc_init(){
	
	
	ADCSRA = 0b11100111; // Initialize the ADC.
	ADCSRB = 0b00000000; // Make sure the register is clear
	
	DIDR0 = 0b00111110; // oNLY READING FROM ADC0
	
	
}


int LEDoutput(int n){
	
	/// This function is a look-up table on how to determine which LED segs to light. Note: In the word doc file, the number to seg correlation can be found on a scanned hand written paper
	
	int val = 0b00000000;
	switch(n) {
		
		
		
		case 0: // The LED number to display is 0
		val= 0b00111111; // This value correlates to displaying a 0 on the 7 seg
		break;
		
		case 1: // The LED number to display is 1
		val= 0b00011000; // This value correlates to displaying a 1 on the 7 seg
		break;
		
		case 2: // The LED number to display is 2
		val= 0b01101101; // This value correlates to displaying a 2 on the 7 seg
		break;
		
		case 3: // The LED number to display is 3
		val= 0b01111100; // This value correlates to displaying a 3 on the 7 seg
		break;
		
		case 4: // The LED number to display is 4
		val= 0b01011010; // This value correlates to displaying a 4 on the 7 seg
		break;
		
		case 5: // The LED number to display is 5
		val= 0b01110110; // This value correlates to displaying a 5 on the 7 seg
		break;
		
		case 6: // The LED number to display is 6
		val= 0b01110111; // This value correlates to displaying a 6 on the 7 seg
		break;
		
		case 7: // The LED number to display is 7
		val= 0b00011100; // This value correlates to displaying a 7 on the 7 seg
		break;
		
		case 8: // The LED number to display is 8
		val= 0b01111111; // This value correlates to displaying a 8 on the 7 seg
		break;
		
		case 9: // The LED number to display is 9
		val= 0b01111110; // This value correlates to displaying a 9 on the 7 seg
		break;
		
		
		
	}
	
	return val; // Returns the sequence corresponding to the number to seg
	
	
	
	
}



void outputnumber2terminal(int n){
	/// This function outputs any arbitrary 4 digit number to the terminal
	
	
	int numbersinverse[4] = {0,0,0,0}; // Holds the inverse buffer
	
	
	int i = 3; // Read from right to left of number

	if(n==0){ // If digit is 0, send 0 straight away
		digit_send(0);
		
	}
	else{ // It is not 0
		
		
		
		do {
			
			int digit = n % 10; // Get the smallest digit
			numbersinverse[i] = digit; // Set the smallest digit to the right of number to inverse
			n /= 10; // Divide it by 10, so to move to the next digit
			i--;// Go to next digit
			

		} while (n > 0); // Do until it goes to 0.
		
		
		int skipuntilnonzero = 0; // This acts as a bool to determine when a non-zerio is hit
		i = 0;
		while(i!=4){// Go through the inverse number to send the value
			if(numbersinverse[i]!=0) skipuntilnonzero = 1; // A non-zero was hit
			if(skipuntilnonzero==1) digit_send(numbersinverse[i]); // Send the digit of the number
			if(i==1) usart_send ('.'); // This places a '.' after the second digit. So for instance we can have 77.54 F
			
			i++;
		}

		
		
		
	}
	
	
	
	
	
	
	
	usart_send(13); // Send a line-feed to terminal

}





void digit_send(int number){
	// Converts a number into a character of the corresponding number
	
	
	
	usart_send (number+48); // +48 will shift a integar 0-9 into a character 0-9
	
}




void usart_send (unsigned char ch)
{
	while(! (UCSR0A & (1<<UDRE0))); // Wait until can send
	UDR0 = ch; // Set UDR0 to send ch.
}
int main(void)
{
	DDRB = 0b11111111; // B acts as the seg select for the 8 seg.
	DDRD = 0b00111110; // D acts as the selector and the TX/RX
	PORTD = 0b00111110; // D5-D2 acts as the selector. D1 acts as transmitter. D0 acts as reciever
	usart_init(); // Initialize the usart
	adc_init(); // Initialize the adc

	
	
	TCCR1A = 0b00000000;// Make sure it is 0 initially
	TCCR1B = 0b00000011; 	// cs is 010 for clk prescalar of 64, That way each overflow is 64*65536/8M = 1/2th of a second.
	
	
	EICRA = 0b00000010; // Sets the interrupt for falling edge.
	TIMSK1 = 1; // Enables the overflow interrupt.
	sei(); // Enable the interrupt
	
	
	

	while(1)
	{
		
		

		outputadded = ADCH *256 + ADCL; // ADCH holds the upper two bits of the analog, ADCL holds the lower 8 bits of the analog. outputadded contains the sum of the two.




		PORTD = 0b00111010;// Enable LED0
		PORTB = LEDoutput(numbersinverse[0]); // Light the segs corresponding to the first digit
		_delay_ms(1); // Keep the LED on for 1 ms

		PORTD = 0b00110110; // Enable LED1
		PORTB = LEDoutput(numbersinverse[1]); // Light the segs corresponding to the second digit
		PORTB |= 0b10000000; // This enables the dot, since value will be in 12.34
		_delay_ms(1); // Keep the LED on for 1 ms



		PORTD = 0b00101110; // Enable LED2
		PORTB = LEDoutput(numbersinverse[2]); // Light the segs corresponding to the third digit
		_delay_ms(1); // Keep the LED on for 1 ms


		PORTD = 0b00011110; // Enable LED3
		PORTB = LEDoutput(numbersinverse[3]); // Light the segs corresponding to the fourth digit
		_delay_ms(1); // Keep the LED on for 1 ms

		
		
		
		
		PORTD = 0b00111110; // Turn all LEDs off.

		
	}
	
	

	
	
	
	
	
	
	return 0;
}
